home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Celestin Apprentice 7
/
Apprentice-Release7.iso
/
Source Code
/
Pascal
/
Applications
/
NIH Image 1.62b11
/
src
/
Camera.p
< prev
next >
Wrap
Text File
|
1997-03-19
|
47KB
|
1,701 lines
unit Camera;
{Routines used by the NIH Image to support Data Translation
and Scion (LG-3, AG-5 or VG-5) frame grabber cards, and
QuickTime compatible digitizers.}
interface
uses
Types, Memory, QuickDraw, QuickDrawText, Packages, Menus, Events, Fonts,
Scrap, ToolUtils, Resources, Errors, Palettes, StandardFile, Windows,
Controls, TextEdit, Files, Dialogs, TextUtils, Finder, MixedMode, Processes,
QDOffscreen, Components, QuickTimeComponents, ImageCompression, GestaltEqu, OSUtils,
globals, Utilities, Graphics, File1, Analysis, Lut;
function DoAveragingOptions: boolean;
procedure AverageFrames;
procedure GetFrame;
procedure CaptureAndDisplayFrame;
procedure HighlightPixels;
procedure ShowTriggerMessage;
procedure StartDigitizing;
procedure StopDigitizing;
function GetFGPixel (h, v: integer): integer;
procedure WaitForTrigger;
procedure ShowChannel;
procedure ShowVideoControl;
procedure UpdateVideoControl;
procedure DoVideoControl (item: integer);
procedure SelectCameraWindow;
procedure SetOffset (var offset, gain: integer);
procedure SetGain (var offset, gain: integer);
procedure ShowOffsetAndGain (offset, gain: integer);
procedure ShowVideoDialog;
procedure StartFrame;
procedure StopFrame;
implementation
type
IntPtr = ^integer;
var
SavePicBaseAddr: ptr;
StopFlagLoc: IntPtr;
procedure GetGrabDepth(var bitDepth: LongInt);
var
vdigInfo: DigitizerInfo;
begin
if VDGetDigitizerInfo(vdig, vdigInfo) = noErr then begin
if DigitizerMode = digitizeGrayscale then begin
if band(vdigInfo.outputCapabilityFlags, digiOutDoes8) <> 0 then
bitDepth := 8 {first choice}
else if band(vdigInfo.outputCapabilityFlags, digiOutDoes32) <> 0 then
bitDepth := 32 {second choice}
else if (band(vdigInfo.outputCapabilityFlags, digiOutDoes16) <> 0) then
bitDepth := 16; {last choice}
end else begin {capture color}
if band(vdigInfo.outputCapabilityFlags, digiOutDoes32) <> 0 then
bitDepth := 32 {first choice}
else if band(vdigInfo.outputCapabilityFlags, digiOutDoes16) <> 0 then
bitDepth := 16 {second choice}
else if (band(vdigInfo.outputCapabilityFlags, digiOutDoes8) <> 0) then
bitDepth := 8; {last choice}
end;
end;
ShowMessage(StringOf('grab depth=', bitDepth));
end;
procedure SetVideoStandard;
var
err: ComponentResult;
inFlags, outFlags: LongInt;
vdigInfo: DigitizerInfo;
begin
if VDGetDigitizerInfo(vdig, vdigInfo) <> noErr then
exit(SetVideoStandard);
case DigitizerStandard of
NTSCStd: if band(vdigInfo.inputCapabilityFlags, digiInDoesNTSC) <> 0 then
err := VDSetInputStandard(vdig, ntscIn);
PALStd: if band(vdigInfo.inputCapabilityFlags, digiInDoesPAL) <> 0 then
err := VDSetInputStandard(vdig, palIn);
SECAMStd: if band(vdigInfo.inputCapabilityFlags, digiInDoesSECAM) <> 0 then
err := VDSetInputStandard(vdig, secamIn);
otherwise;
end;
err := VDGetCurrentFlags(vdig, inFlags, outFlags);
if err = noErr then
if band(inFlags, digiInDoesNTSC) <> 0 then
DigitizerStandard := NTSCStd
else if band(inFlags, digiInDoesPAL) <> 0 then
DigitizerStandard := PALStd
else if band(inFlags, digiInDoesSECAM) <> 0 then
DigitizerStandard := SECAMStd;
end;
procedure SetVideoInput;
var
err: ComponentResult;
maxChannel, currentChannel: integer;
begin
err := VDGetNumberOfInputs(vdig, maxChannel);
if (VideoChannel <= maxChannel) and (err = noErr) then
err := VDSetInput(vdig, VideoChannel)
else begin
VideoChannel := 0;
err := VDSetInput(vdig, 0);
end;
err := VDGetInput(vdig, currentChannel);
if err = noErr then
VideoChannel := currentChannel;
end;
function SetupVdig: boolean;
var
mPtr: MatrixRecordPtr;
vdErr: ComponentResult;
vdigInfo: DigitizerInfo;
DummyMatrixRecord, bitDepth: LongInt;
err: OSErr;
flags: GWorldFlags;
SaveGDevice: GDHandle;
gwRect, srcRrect: rect;
str: str255;
begin
SetupVdig := false;
SetRect(gwRect, 0, 0, fgWidth, fgHeight);
bitDepth := 8;
GetGrabDepth(bitDepth);
SetVideoInput;
if bitDepth = 8 then
vdErr := VDSetInputColorSpaceMode(vdig, 0); {grayscale}
SaveGDevice := GetGDevice;
SetGDevice(osGDevice);
if bitDepth = 8 then
GWorldLUT := GetCTable(40) {grayscale LUT}
else
GWorldLUT := nil;
flags := 0;
err := NewGWorld(osGWorld, bitDepth, gwRect, GWorldLUT, nil, flags);
SetGDevice(SaveGDevice);
if err <> NoErr then begin
PutMemoryAlert;
CloseVdig;
exit(SetupVdig);
end;
fgPixMap := GetGWorldPixMap(osGWorld);
if not LockPixels(fgPixMap) then begin
CloseVdig;
exit(SetupVdig);
end;
{err := LockMemoryContiguous(GetPixBaseAddr(fgPixMap), 2097152);}
vdErr := VDGetActiveSrcRect(vdig, 0, srcRrect);
if vdErr = noErr then
vdErr := VDSetDigitizerRect(vdig, srcRrect);
DummyMatrixRecord := LongInt(nil);
mPtr := MatrixRecordPtr(ptr(DummyMatrixRecord));
vdErr := VDSetPlayThruDestination(vdig, fgPixMap, gwRect, MatrixRecord(mPtr^), nil);
if vdErr = noErr then
SetupVdig := true
else begin
CloseVdig;
if vdErr = -2208 then
str := concat(cr, '(Try turning virtual memory or RAM Doubler off.)')
else
str := '';
PutError(StringOf('Video digitizer error ', vdErr, str));
end;
end;
procedure LookForVDig(var vdigError: boolean);
{Look for a QuickTime video digitizer component}
var
result: LongInt;
videoDesc: ComponentDescription;
srcRrect: rect;
vdErr: ComponentResult;
vdigID: Component;
begin
vdigError := false;
if Gestalt(gestaltQuickTime, result) <> noErr then begin
ShowMessage('No QuickTime');
exit(LookForVDig);
end;
{$IFC PowerPC}
if Gestalt(gestaltQuickTimeFeatures, result) <> noErr then begin
ShowMessage('No QuickTime PPC support');
exit(LookForVDig);
end;
{$ENDC}
videoDesc.componentType := VideoDigitizerComponentType;
videoDesc.componentSubType := OSType(0); {any subtype}
if UseBuiltinDigitizer then
videoDesc.componentManufacturer := 'appl'
else
videoDesc.componentManufacturer := OSType(0);
videoDesc.componentFlags := 0;
videoDesc.componentFlagsMask := 0;
vdigID :=FindNextComponent(Component(0), videoDesc);
if vdigID = Component(0) then begin
videoDesc.componentManufacturer := OSType(0); {any manufacturer}
vdigID :=FindNextComponent(Component(0), videoDesc);
if vdigID = Component(0) then begin
ShowMessage('No vdig found');
exit(LookForVDig);
end;
end;
vdig := OpenComponent(vdigID);
if vdig = nil then begin
ShowMessage('Unable to open vdig');
vdigError := true;
exit(LookForVDig);
end;
SetVideoStandard;
vdErr := VDGetDigitizerRect(vdig, srcRrect);
{vdErr := VDGetActiveSrcRect(vdig, 0, srcRrect);}
if vdErr = noErr then with srcRrect do begin
fgWidth := (right - left) div fgScale;
fgHeight := (bottom - top) div fgScale;
end else begin
fgWidth := 320;
fgHeight := 240;
end;
FrameGrabber := QTvdig;
if not SetupVdig then
vdigError := true;
HighlightSaturatedPixels := false;
end;
procedure CorrectShadingOfLine (PicPtr, BFPtr: ptr; width, BFMean: integer);
{$IFC PowerPC}
VAR
PicLine,BFLine:LinePtr;
i,value:LongInt;
BEGIN
PicLine:=LinePtr(PicPtr);
BFLine:=LinePtr(BFPtr);
FOR i:=0 TO width-1 DO BEGIN
value:=PicLine^[i];
value:=255-value;
value:=(value * BFMean + (BFLine^[i] div 2)) DIV BFLine^[i];
IF value>254 THEN value:=254;
IF value<1 THEN value:=1;
PicLine^[i]:=255-value;
END;
END;
{$ELSEC}
{a0=data pointer}
{a1=blank field data pointer}
{d0=count}
{d1=pixel value}
{d2=blank field pixel value}
{d3=blank field mean}
{d4=temp}
{d5=max pixel value(245)}
{d6=min pixel value(1)}
inline
$4E56, $0000, { link a6,#0}
$48E7, $FEC0, { movem.l a0-a1/d0-d6,-(sp)}
$206E, $000C, { move.l 12(a6),a0}
$226E, $0008, { move.l 8(a6),a1}
$4280, { clr.l d0}
$302E, $0006, { move.w 6(a6),d0}
$362E, $0004, { move.w 4(a6),d3}
$2A3C, $0000, $00FE, { move.l #254,d5}
$2C3C, $0000, $0001, { move.l #1,d6}
$5380, { subq.l #1,d0}
$4281, { clr.l d1}
$4282, { clr.l d2}
$1210, {L1 move.b (a0),d1}
$1419, { move.b (a1)+,d2}
$4601, { not.b d1}
$C2C3, { mulu.w d3,d1}
$2802, { move.l d2,d4}
$E244, { asr.w #1,d4}
$D284, { add.l d4,d1}
$82C2, { divu.w d2,d1}
$B245, { cmp.w d5,d1}
$6F02, { ble.s L2}
$3205, { move.w d5,d1}
$B246, {L2 cmp.w d6,d1}
$6C02, { bge.s L3}
$3206, { move.w d6,d1}
$4601, {L3 not.b d1}
$10C1, { move.b d1,(a0)+}
$51C8, $FFDE, { dbra d0,L1}
$4CDF, $037F, { movem.l (sp)+,a0-a1/d0-d6}
$4E5E, { unlk a6}
$DEFC, $000C; { add.w #12,sp}
{$ENDC}
procedure CorrectShading;
var
i, tag, width: integer;
offset, NextUpdate: LongInt;
p1, p2: ptr;
str: str255;
MaskRect:rect;
begin
with info^ do begin
if ImageSize <> BlankFieldInfo^.ImageSize then begin
beep;
exit(CorrectShading);
end;
ShowWatch;
tag:=0;
NextUpdate:=TickCount+6;
width:=PicRect.right;
p1 := PicBaseAddr;
p2 := BlankFieldInfo^.PicBaseAddr;
for i := 1 to nLines do begin
CorrectShadingOfLine(p1, p2, PixelsPerLine, BlankFieldMean);
p1 := ptr(ord4(p1) + info^.BytesPerRow);
p2 := ptr(ord4(p2) + BlankFieldInfo^.BytesPerRow);
if TickCount>=NextUpdate then begin
SetRect(MaskRect, 0, tag, width, i);
UpdateScreen(MaskRect);
tag:=i;
NextUpdate:=TickCount+6;
end;
end;
SetRect(MaskRect, 0, tag, width, nLines);
UpdateScreen(MaskRect);
str := title;
if SpatiallyCalibrated then
str := concat(str, chr($13)); {Black Diamond}
if fit <> uncalibrated then
str := concat(str, '');
if wptr <> nil then
SetWTitle(wptr, concat(str, ' (Corrected)'));
end;
end;
procedure CopyVdigImageOffscreen;
var
SaveExtraColors: integer;
begin
with info^ do begin
SaveExtraColors := 0;
if (LUTMode = Grayscale) and (not IdentityFunction or (nExtraColors <> 0)) then begin
SaveExtraColors := nExtraColors;
nExtraColors := 0;
ResetGrayMap;
end;
CopyOffscreen(fgPixMap, osPort^.portPixMap, PicRect, PicRect);
if SaveExtraColors <> 0 then begin
nExtraColors := SaveExtraColors;
LoadLUT(ctable);
end;
UpdatePicWindow;
end; {with}
end;
procedure StartFrame;
begin
if CurrentBufferIsZero then begin
if FrameGrabber = ScionAG5 then
BufferReg^ := $81
else
BufferReg^ := 0
end else begin
if FrameGrabber = ScionAG5 then
BufferReg^ := $89
else
BufferReg^ := 1;
end;
if ExternalTrigger then begin
if FrameGrabber = ScionAG5 then
ControlReg^ := bor(bor(ord(AG5GrabMode), $90), bsl(ord(AG5LutMode and not ControlKeyDown), 2))
else
ControlReg^ := $90 {Start frame capture}
end else begin
if FrameGrabber = ScionAG5 then
ControlReg^ := bor(bor(ord(AG5GrabMode), $80), bsl(ord(AG5LutMode and not ControlKeyDown), 2))
else
ControlReg^ := $80; {Start frame capture}
end;
end;
procedure StopFrame;
var
ticks, timeout: LongInt;
begin
if ExternalTrigger then begin {Wait for trigger}
repeat
if button then
ExternalTrigger := false;
until (BitAnd(ControlReg^, $80) = $80) or not ExternalTrigger;
ControlReg^ := 0;
end {if External Trigger}
else begin
TimeOut := TickCount + 30; {1/2sec. timeout}
while BitAnd(ControlReg^, $80) = 0 do begin {Wait for it to complete}
if TickCount > TimeOut then begin
ControlReg^ := 0;
leave
end;
end;
ControlReg^ := 0;
end;
with fgPort^ do
with PortPixMap^^ do
if CurrentBufferIsZero then
BaseAddr := ptr(fgSuperSlotBase0)
else
BaseAddr := ptr(fgSuperSlotBase1);
CurrentBufferIsZero := not CurrentBufferIsZero;
fgFrameCount := fgFrameCount + 1;
end;
procedure StopDigitizing;
begin
if digitizing then
with info^ do begin
ShowFrameRate('', fgStartTicks, fgFrameCount);
if vdig <> nil then
CopyVdigImageOffscreen
else
CopyOffscreen(fgPixMap, osPort^.portPixMap, PicRect, PicRect);
SetMenuItemText(SpecialMenuH, StartItem, 'Start Capturing');
Digitizing := false;
ContinuousHistogram := false;
if DoubleBuffering then begin
StopFrame;
BufferReg^ := 0;
CurrentBufferIsZero := true;
DoubleBuffering := false;
with fgPort^ do
with PortPixMap^^ do
BaseAddr := ptr(fgSuperSlotBase0)
end;
with info^ do
if PictureType = FrameGrabberType then begin
title := 'Camera';
UpdateTitleBar;
if HighlightSaturatedPixels then
LoadLUT(ctable);
end;
if (ScreenDepth<>8) and HighlightSaturatedPixels then
UpdatePicWindow;
if (BlankFieldInfo <> nil) and not OptionKeyDown then
CorrectShading;
end;
end;
procedure GetFrame;
var
ticks, timeout: LongInt;
temp:integer;
vdigErr: ComponentResult;
begin
case FrameGrabber of
ScionLG3, ScionVG5f:
if ExternalTrigger then begin {Wait for trigger}
ControlReg^ := $90;
repeat
if button then
ExternalTrigger := false;
until (band(ControlReg^, $80) = $80) or not ExternalTrigger;
ControlReg^ := 0;
if Digitizing then
StopDigitizing;
UpdateVideoControl;
end {if External Trigger}
else begin
TimeOut := TickCount + 30; {1/2sec. timeout}
ControlReg^ := $80; {Start frame capture}
while band(ControlReg^, $80) = 0 do begin {Wait for it to complete}
if TickCount > TimeOut then begin
ControlReg^ := 0;
leave
end;
end;
ControlReg^ := 0;
end;
ScionAG5:
if ExternalTrigger then begin {Wait for trigger}
ControlReg^ := bor(bor(ord(AG5GrabMode), $90), bsl(ord(AG5LutMode and not ControlKeyDown), 2));
repeat
if button then
ExternalTrigger := false;
until (band(ControlReg^, $80) = $80) or not ExternalTrigger;
ControlReg^ := 0;
if Digitizing then
StopDigitizing;
UpdateVideoControl;
end {if External Trigger}
else begin
TimeOut := TickCount + 30; {1/2sec. timeout}
ControlReg^ := bor(bor(ord(AG5GrabMode), $80), bsl(ord(AG5LutMode and not ControlKeyDown), 2)); {Start frame capture}
repeat
if TickCount > TimeOut then
leave;
temp:=ControlReg^; {ppc-bug}
until band(temp, $80) <> 0; {Wait for it to complete}
ControlReg^ := 0;
end;
QuickCapture:
if ExternalTrigger then begin {Wait for trigger}
ControlReg^ := $82; {Set Busy and External Trigger Enable bits}
repeat
if button then
ExternalTrigger := false;
temp:=ControlReg^; {ppc-bug}
until (band(temp, $80) = 0) or not ExternalTrigger;
if Digitizing then
StopDigitizing;
UpdateVideoControl;
end {if External Trigger}
else begin
TimeOut := TickCount + 30; {1/2sec. timeout}
ControlReg^ := $80; {Start frame capture by setting busy bit}
repeat
if TickCount > TimeOut then
leave;
temp:=ControlReg^; {ppc-bug}
until band(temp, $80) = 0; {Wait for frame capture to complete}
end;
QTvdig: begin
if ExternalTrigger then begin {Wait for mouse press}
repeat
until button;
ExternalTrigger := false;
end;
if vdig <> nil then
vdigErr := VDGrabOneFrame(vdig);
end;
end; {case}
fgFrameCount := fgFrameCount + 1;
end;
procedure CaptureAndDisplayFrame;
var
tPort: GrafPtr;
SaveGDevice: GDHandle;
begin
with info^ do begin
if (PictureType <> FrameGrabberType) or (PixelsPerLine <> fgWidth) or (nlines <> fgHeight) then begin
Digitizing := false;
exit(CaptureAndDisplayFrame);
end;
if DoubleBuffering then begin
StopFrame;
StartFrame;
end else
GetFrame;
SaveGDevice := GetGDevice;
SetGDevice(GetMainDevice);
getPort(tPort);
SetPort(wptr);
SetFColor(BlackIndex);
SetBColor(WhiteIndex);
if (FrameGrabber = QTvdig) and (LUTMode <> grayscale) and (ScreenDepth <= 8) then
CopyBits(BitMapHandle(fgPixMap)^^, BitMapHandle(CGrafPtr(wptr)^.PortPixMap)^^, SrcRect, wrect, ditherCopy, nil)
else
CopyBits(BitMapHandle(fgPixMap)^^, BitMapHandle(CGrafPtr(wptr)^.PortPixMap)^^, SrcRect, wrect, srcCopy, nil);
SetPort(tPort);
SetGDevice(SaveGDevice);
end;
end;
procedure SetReg (index, value: integer);
const
RegOffset = $f5fe0;
var
reg: ptr;
begin
reg := ptr(fgSlotBase + RegOffset + index * 4);
reg^ := value;
end;
{$ifc PowerPC} {ppc-bug}
procedure SwapMMUMode(var mode:SignedByte);
begin
end;
{$endc}
procedure SelectCameraWindow;
{If there is a Camera window, activate it, otherwise, do nothing.}
var
i: integer;
TempInfo: InfoPtr;
begin
for i := 1 to nPics do begin
TempInfo := pointer(WindowPeek(PicWindow[i])^.RefCon);
if TempInfo^.PictureType = FrameGrabberType then begin
if PicWindow[i] <> nil then begin
if OpPending then
KillRoi;
SelectWindow(PicWindow[i]);
Info := TempInfo;
ActivateWindow;
end; {if}
leave;
end; {if}
end; {for}
end;
procedure HighlightPixels;
var
lut: MyCSpecArray;
begin
with info^ do begin
lut := ctable;
lut[1].rgb := Highlight1;
lut[254].rgb := Highlight254;
LoadLUT(lut);
end;
end;
procedure ShowTriggerMessage;
begin
if ExternalTrigger and (frameGrabber <> noFrameGrabber) then
ShowMessage(concat('EXTERNAL TRIGGER MODE', crStr, '(Press mouse button to exit)'));
end;
procedure StartDigitizing;
var
i, width, height: integer;
trect: rect;
NewWindow: boolean;
vdigError: boolean;
begin
if FrameGrabber = NoFrameGrabber then begin
LookForVDig(vdigError);
if vdigError then
exit(StartDigitizing);
end;
if FrameGrabber = NoFrameGrabber then begin
PutError('Capturing requires a Data Translation, Scion or QuickTime compatible frame grabber.');
AbortMacro;
exit(StartDigitizing)
end;
if Digitizing then begin
StopDigitizing;
if BlankFieldInfo <> nil then
wait(15);
FlushEvents(EveryEvent, 0); {In case user holds key down too long}
exit(StartDigitizing)
end;
if info^.PictureType <> FrameGrabberType then
SelectCameraWindow;
NewWindow := false;
with info^ do
if (PictureType <> FrameGrabberType) or (PixelsPerLine <> fgWidth) or (nlines <> fgHeight) then begin
if not NewPicWindow('Camera', fgWidth, fgHeight) then
exit(StartDigitizing);
if FrameGrabber = QTvdig then with info^ do begin
fgPort := osPort;
fgSlotBase := LongInt(PicBaseAddr);
fgRowBytes := BytesPerRow;
end;
NewWindow := true;
end;
with info^ do begin
PictureType := FrameGrabberType;
if NewWindow and (not EqualRect(SrcRect, PicRect)) then {Center Frame}
with SrcRect do begin
width := right - left;
height := bottom - top;
left := (PicRect.right - width) div 2;
right := left + width;
top := (PicRect.bottom - height) div 2;
bottom := top + height;
end;
KillRoi;
if ScaleToFitWindow then
ScaleToFit;
with SrcRect do begin
width := right - left;
left := band(left, $fffc);
right := left + width;
end;
GetWindowRect(wptr, trect);
with trect do
if band(left, 3) <> 0 then
MoveWindow(wptr, band(left, $fffc), top, true); {Forces window to be word aligned}
with SrcRect do {Prevents bus errors when Camera window moved.}
if (top = 0) and (bottom < PicRect.bottom) then begin
top := top + 1;
bottom := bottom + 1;
end;
ResetFrameGrabber;
Digitizing := true;
SetMenuItemText(SpecialMenuH, StartItem, 'Stop Capturing');
changes := true;
BinaryPic := false;
UpdateTitleBar;
if HighlightSaturatedPixels then
HighlightPixels;
end; {with info}
fgFrameCount := 0;
fgStartTicks := TickCount;
ContinuousHistogram := false;
ShowTriggerMessage;
if PCIFramegrabber and not ExternalTrigger then begin
DoubleBuffering := true;
CurrentBufferIsZero := true;
StartFrame;
end;
end;
procedure AddLineToSum (src, dst: ptr; width: LongInt);
{$IFC PowerPC}
type
SumLineType = array[0..2047] of integer;
fptr = ^SumLineType;
var
FrameLine: LinePtr;
SumLine: fptr;
i: integer;
begin
FrameLine := LinePtr(src);
SumLine := fptr(dst);
for i := 0 to width - 1 do
SumLine^[i] := SumLine^[i] + FrameLine^[i];
end;
{$ELSEC}
inline
{a0=data pointer}
{a1=sum buffer pointer}
{d0=count}
{d1=pixel value}
{d2=temp}
$4E56, $0000, {link a6,#0}
$48E7, $E0C0, {movem.l a0-a1/d0-d2,-(sp)}
$206E, $000C, {move.l 12(a6),a0}
$226E, $0008, {move.l 8(a6),a1}
$202E, $0004, {move.l 4(a6),d0}
$5380, {subq.l #1,d0}
$4281, {clr.l d1}
$4282, {clr.l d2}
$1218, {L1 move.b (a0)+,d1}
$3411, {move.w (a1),d2}
$D441, {add.w d1,d2}
$32C2, {move.w d2,(a1)+}
$51C8, $FFF6, {dbra d0,L1}
$4CDF, $0307, {movem.l (sp)+,a0-a1/d0-d2}
$4E5E, {unlk a6}
$DEFC, $000C; {add.w #12,sp}
{$ENDC}
function DoAveragingOptions: boolean;
const
FramesID = 8;
VideoRateID = 9;
SumID = 10;
ShowID = 11;
FixID = 12;
MinID = 13;
MaxID = 14;
OnChipID = 15;
var
mylog: DialogPtr;
item, i: integer;
begin
InitCursor;
mylog := GetNewDialog(140, nil, pointer(-1));
if not SumFrames then begin
ShowIntegratedValues := false;
FixIntegrationScale := false;
end;
SetDNum(MyLog, FramesID, FramesToAverage);
SetDlogItem(mylog, SumID, ord(SumFrames));
SetDlogItem(mylog, VideoRateID, ord(VideoRateAveraging));
SetDlogItem(mylog, ShowID, ord(ShowIntegratedValues));
SetDlogItem(mylog, FixID, ord(FixIntegrationScale));
SetDlogItem(mylog, OnChipID, ord(IntegrateOnChip));
SetDNum(MyLog, MinID, IntegrationMin);
SetDNum(MyLog, MaxID, IntegrationMax);
SelectDialogItemText(MyLog, FramesID, 0, 32767);
repeat
ModalDialog(nil, item);
if item = FramesID then
FramesToAverage := GetDNum(MyLog, FramesID);
if item = SumID then begin
SumFrames := not SumFrames;
if SumFrames then
IntegrateOnChip := false
else begin
FixIntegrationScale := false;
ShowIntegratedValues := false;
end;
SetDlogItem(mylog, SumID, ord(SumFrames));
SetDlogItem(mylog, FixID, ord(FixIntegrationScale));
SetDlogItem(mylog, ShowID, ord(ShowIntegratedValues));
SetDlogItem(mylog, OnChipID, ord(IntegrateOnChip));
end;
if item = VideoRateID then begin
VideoRateAveraging := not VideoRateAveraging;
if VideoRateAveraging then
IntegrateOnChip := false;
SetDlogItem(mylog, VideoRateID, ord(VideoRateAveraging));
SetDlogItem(mylog, OnChipID, ord(IntegrateOnChip));
end;
if item = ShowID then begin
ShowIntegratedValues := not ShowIntegratedValues;
if ShowIntegratedValues then begin
SumFrames := true;
IntegrateOnChip := false;
end;
SetDlogItem(mylog, ShowID, ord(ShowIntegratedValues));
SetDlogItem(mylog, SumID, ord(SumFrames));
SetDlogItem(mylog, OnChipID, ord(IntegrateOnChip));
end;
if item = FixID then begin
FixIntegrationScale := not FixIntegrationScale;
if FixIntegrationScale then begin
SumFrames := true;
IntegrateOnChip := false;
end;
SetDlogItem(mylog, FixID, ord(FixIntegrationScale));
SetDlogItem(mylog, SumID, ord(SumFrames));
SetDlogItem(mylog, OnChipID, ord(IntegrateOnChip));
end;
if (item = MinID) or (item = MaxID) then begin
if item = MinID then
IntegrationMin := GetDNum(MyLog, MinID)
else
IntegrationMax := GetDNum(MyLog, MaxID);
SumFrames := true;
FixIntegrationScale := true;
IntegrateOnChip := false;
SetDlogItem(mylog, SumID, ord(SumFrames));
SetDlogItem(mylog, FixID, ord(FixIntegrationScale));
SetDlogItem(mylog, OnChipID, ord(IntegrateOnChip));
end;
if item = OnChipID then begin
IntegrateOnChip := not IntegrateOnChip;
if IntegrateOnChip then begin
SumFrames := false;
VideoRateAveraging := false;
FixIntegrationScale := false;
ShowIntegratedValues := false;
end;
SetDlogItem(mylog, OnChipID, ord(IntegrateOnChip));
SetDlogItem(mylog, SumID, ord(SumFrames));
SetDlogItem(mylog, VideoRateID, ord(VideoRateAveraging));
SetDlogItem(mylog, FixID, ord(FixIntegrationScale));
SetDlogItem(mylog, ShowID, ord(ShowIntegratedValues));
end;
until (item = ok) or (item = cancel);
DisposeDialog(mylog);
if FramesToAverage < 2 then
FramesToAverage := 2;
if IntegrationMin < 0 then
IntegrationMin := 0;
if IntegrationMax > 32767 then
IntegrationMax := 32767;
if VideoRateAveraging and (item <> cancel) then begin
if (FrameGrabber <> ScionLG3) and (FrameGrabber <> ScionAG5) then begin
VideoRateAveraging := false;
PutError('Video rate averaging or summation requires a Scion LG-3 or a Scion AG-5.');
DoAveragingOptions := false;
exit(DoAveragingOptions);
end;
if (FrameGrabber = ScionLG3) and (FramesToAverage > MaxLG3Frames) then begin
FramesToAverage := MaxLG3Frames;
DoAveragingOptions := false;
PutError(concat('This ', long2str(MaxLG3Frames div 2), 'MB LG-3 can capture a maximum of ', long2str(MaxLG3Frames), ' frames at video rates.'));
exit(DoAveragingOptions);
end;
if (FrameGrabber = ScionAG5) and (FramesToAverage > 127) then begin
FramesToAverage := 127;
DoAveragingOptions := false;
PutError(concat('The AG-5 can average or sum a maximum of 127 frames at video rates.'));
exit(DoAveragingOptions);
end;
end;
if IntegrateOnChip and (item <> cancel) then
if (FrameGrabber <> ScionLG3) and (FrameGrabber <> ScionAG5) and (FrameGrabber <> ScionVG5f) then begin
IntegrateOnChip := false;
PutError('On-chip integration requires a Scion frame grabber.');
DoAveragingOptions := false;
exit(DoAveragingOptions);
end;
DoAveragingOptions := item <> cancel;
end;
function OddEven: boolean;
{Looks at the the Field Status bit of the Status Register,
which has the same address as Control Register 1. This bit is
high during the odd field and low during the even field.}
begin
if band(ControlReg^, $10) = $10 then
OddEven := true
else
OddEven := false;
end;
procedure WaitForOdd;
var
timeout: LongInt;
begin
TimeOut := TickCount + 30; {1/2sec. timeout}
while OddEven do
if TickCount > TimeOut then
Exit(WaitForOdd);
TimeOut := TickCount + 30; {1/2sec. timeout}
while not OddEven do
if TickCount > TimeOut then
Exit(WaitForOdd);
end;
procedure IntegrateOn;
{Sets bit 3 (Open Drain Output) of Control Register 1 high
which pulls pin 11 of the 15 pin connector low, causing the
Cohu camera to start integrating.}
begin
ControlReg^ := $08;
end;
procedure IntegrateOff;
{Sets bit 3 of Control Register 1 low which open circuits
pin 11, causing the Cohu camera to stop integrating.}
begin
ControlReg^ := $00;
end;
procedure DoOnChipIntegration;
{Requires a Scion LG-3, a Cohu 4910 series camera, and a cable available from Scion.}
var
i,StartTicks:LongInt;
str:str255;
begin
WaitForOdd;
IntegrateOn;
StartTicks := TickCount;
for i := 1 to FramesToAverage - 1 do begin
WaitForOdd;
if (i mod 30) = 0 then
ShowAnimatedWatch;
if CommandPeriod then
leave;
end;
IntegrateOff;
GetFrame;
RealToString((TickCount - StartTicks) / 60.0, 1, 2, str);
ShowFrameRate(concat(Long2str(FramesToAverage), ' frames', cr, str, ' seconds', cr), StartTicks, FramesToAverage);
with info^ do
CopyOffscreen(fgPixMap, osPort^.portPixMap, RoiRect, RoiRect);
UpdatePicWindow;
KillRoi;
if BlankFieldInfo <> nil then
CorrectShading;
if info^.fit<>uncalibrated then
RemoveDensityCalibration;
end;
procedure DoHardwareAveraging;
{Do averaging or integration at video rates using the Scion Ag-5.}
var
StartTicks,ActualMin,ActualMax:LongInt;
str1,str2:str255;
frame,i:integer;
roi:rect;
begin
roi:=info^.RoiRect;
KillRoi;
if FramesToAverage > 127 then
FramesToAverage := 127;
ExternalTrigger := false;
AG5GrabMode := GrabNormal;
GetFrame;
StartTicks := TickCount;
AG5GrabMode := GrabSum;
for frame := 1 to FramesToAverage - 1 do begin
GetFrame;
end;
RealToString((TickCount - StartTicks) / 60.0, 1, 2, str2);
if not SumFrames then begin
ConstantReg^ := FramesToAverage;
AG5GrabMode := GrabDivide;
GetFrame;
AG5GrabMode := GrabNormal;
str1 := '';
end
else begin
ActualMin := Ord4(ScaleLowReg^);
ActualMax := Ord4(ScaleHighReg^);
if FixIntegrationScale then begin
ScaleLowReg^ := integer(IntegrationMin);
ScaleHighReg^ := integer(IntegrationMax);
end;
AG5GrabMode := GrabScale;
GetFrame;
AG5GrabMode := GrabNormal;
if FixIntegrationScale then
str1 := concat('min=', long2str(IntegrationMin), ' (', long2str(ActualMin), ')', cr, 'max=', long2str(IntegrationMax), ' (', long2str(ActualMax), ')', cr)
else
str1 := concat('min=', long2str(ActualMin), cr, 'max=', long2str(ActualMax), cr)
end;
ShowFrameRate(concat(Long2str(FramesToAverage), ' frames', cr, str1, str2, ' seconds', cr), StartTicks, FramesToAverage);
with info^ do
CopyOffscreen(fgPixMap, osPort^.portPixMap, roi, roi);
UpdatePicWindow;
if not EqualRect(roi, info^.PicRect) then
RestoreRoi;
if BlankFieldInfo <> nil then
CorrectShading;
if ShowIntegratedValues then with info^ do begin
fit := StraightLine;
nCoefficients := 2;
coefficient[2] := (ActualMax - ActualMin) / 253.0;
coefficient[1] := ActualMin - coefficient[2];
ZeroClip := false;
UpdateTitleBar;
if macro then
GenerateValues;
end else
if SumFrames and (info^.fit<>uncalibrated) then
RemoveDensityCalibration;
end; {DoAG5HardwareAveraging}
procedure AverageFrames;
type
IntPtr = ^integer;
SumLineType = array[0..2047] of integer;
sptr = ^SumLineType;
var
AutoSelectAll: boolean;
SelectionSize, FrameBufferSize, offset, StartTicks: LongInt;
SumBase, src, srcbase, dst, OffscreenBase: ptr;
str1, str2: str255;
xLines, xPixelsPerLine, BytesPerLine, frame, line, pixel: integer;
aline, BlankLine: LineType;
GrabRect: rect;
hstart, vstart, wwidth, wheight: integer;
j, FramesAveraged: integer;
SrcRowBytes, DstRowBytes, i, value, MinV, MaxV, range, ActualMin, ActualMax: LongInt;
iptr: IntPtr;
FrameLine: LinePtr;
SumLine: sptr;
SaveBlankFieldInfo: InfoPtr;
myMMUMode: signedbyte;
begin
with info^ do
if PictureType <> FrameGrabberType then begin
PutError('You must have an active Camera window (created using Start Capturing) in order to average frames.');
AbortMacro;
exit(AverageFrames)
end;
if NotRectangular or NotinBounds then begin
AbortMacro;
exit(AverageFrames);
end;
if (not OptionKeyWasDown) and (not macro) then begin
if not DoAveragingOptions then
exit(AverageFrames);
end;
SaveBlankFieldInfo := BlankFieldInfo;
BlankFieldInfo := nil; {We don't want to do shading correction now}
StopDigitizing;
BlankFieldInfo := SaveBlankFieldInfo;
OptionKeyWasDown := false;
if (FrameGrabber <> ScionLG3) and (FrameGrabber <> ScionAG5) then
VideoRateAveraging := false;
if (FrameGrabber <> ScionLG3) and (FrameGrabber <> ScionAG5) and (FrameGrabber <> ScionVG5f) then
IntegrateOnChip := false;
ShowWatch;
ShowTriggerMessage;
AutoSelectAll := not Info^.RoiShowing;
if AutoSelectAll then
SelectAll(false);
WhatToUndo := NothingToUndo;
ContinuousHistogram := false;
ResetFrameGrabber;
if IntegrateOnChip then begin
DoOnChipIntegration;
exit(AverageFrames);
end;
if VideoRateAveraging and (FrameGrabber=ScionAg5) then begin
DoHardwareAveraging;
exit(AverageFrames);
end;
DrawLabels('Frame:', 'Total:', '');
with info^.RoiRect do
SelectionSize := (ord4(right) - left) * (bottom - top);
FrameBufferSize := SelectionSize * 2;
if FrameBufferSize > BigBufSize then begin
NumToString((FrameBufferSize div 2) div 1024, str1);
str1 := concat('It must be enlarged to at least ', str1, 'K bytes.');
PutError(concat('The Undo/Clipboard buffer is too small to average the frames. ', str1));
if AutoSelectAll or (BlankFieldInfo <> nil) then
KillRoi
else
ShowRoi;
exit(AverageFrames)
end;
WhatsOnClip := NothingOnClip;
SumBase := BigBuf;
with info^, info^.RoiRect do begin
offset := left + ord4(top) * BytesPerRow;
OffscreenBase := ptr(ord4(PicBaseAddr) + offset);
offset := left + ord4(top) * fgRowBytes;
srcbase := ptr(ord4(ptr(fgSlotBase)) + offset);
SrcRowBytes := fgRowBytes;
xLines := bottom - top;
xPixelsPerLine := right - left;
BytesPerLine := xPixelsPerLine * 2;
end; {with}
for i := 0 to BytesPerLine - 1 do
BlankLine[i] := WhiteIndex;
dst := SumBase;
for line := 1 to xLines do begin {zero buffer}
BlockMove(@BlankLine, dst, BytesPerLine);
dst := ptr(ord4(dst) + BytesPerLine);
end;
info^.title := 'Camera';
UpdateTitleBar;
StartTicks := TickCount;
if VideoRateAveraging then begin
if FramesToAverage > MaxLG3Frames then
FramesToAverage := MaxLG3Frames;
ExternalTrigger := false;
BufferReg^ := 0;
GetFrame;
StartTicks := TickCount - 2;
for frame := 1 to FramesToAverage - 1 do begin
BufferReg^ := Frame;
GetFrame;
end;
BufferReg^ := 0;
RealToString((TickCount - StartTicks) / 60.0, 1, 2, str1);
ShowFrameRate(concat(Long2str(FramesToAverage), ' frames', crStr, str1, ' seconds', crStr), StartTicks, FramesToAverage);
end; {if VideoRateAveraging}
for frame := 0 to FramesToAverage - 1 do begin
Show2Values(frame + 1, FramesToAverage);
if VideoRateAveraging then
BufferReg^ := Frame
else begin
GetFrame;
if FrameGrabber = QTvdig then with info^ do
CopyOffScreen(fgPixMap, osPort^.portPixMap, roiRect, roiRect);
end;
src := srcbase;
dst := SumBase;
myMMUMode := 1;
SwapMMUMode(myMMUMode);
for line := 1 to xLines do begin
AddLineToSum(src, dst, xPixelsPerLine);
src := ptr(ord4(src) + SrcRowBytes);
dst := ptr(ord4(dst) + BytesPerLine);
end;
SwapMMUMode(myMMUMode);
if CommandPeriod then begin
beep;
if AutoSelectAll then
KillRoi
else
ShowRoi;
exit(AverageFrames);
end;
end; {for}
src := SumBase;
dst := OffscreenBase;
DstRowBytes := info^.BytesPerRow;
if SumFrames then begin
MinV := 2000000000;
MaxV := 0;
iptr := IntPtr(src);
for i := 1 to SelectionSize do begin
value := iptr^;
if value > MaxV then
MaxV := value;
if value < MinV then
MinV := value;
iptr := IntPtr(ord4(iptr) + 2);
end;
ActualMin := MinV;
ActualMax := MaxV;
if FixIntegrationScale then begin
MinV := IntegrationMin;
MaxV := IntegrationMax;
end;
range := MaxV - MinV;
if range <> 0 then
for line := 1 to xLines do begin
SumLine := sptr(src);
FrameLine := LinePtr(dst);
for j := 0 to xPixelsPerLine - 1 do begin
value := ord4(SumLine^[j] - MinV) * 253 div range + 1;
if value < 0 then
value := 0;
if value > 255 then
value := 255;
FrameLine^[j] := value;
end;
src := ptr(ord4(src) + BytesPerLine);
dst := ptr(ord4(dst) + DstRowBytes);
end
else
beep;
end
else
for line := 1 to xLines do begin
SumLine := sptr(src);
FrameLine := LinePtr(dst);
for j := 0 to xPixelsPerLine - 1 do
FrameLine^[j] := SumLine^[j] div FramesToAverage;
src := ptr(ord4(src) + BytesPerLine);
dst := ptr(ord4(dst) + DstRowBytes);
end;
if not VideoRateAveraging then begin
if SumFrames then begin
if FixIntegrationScale then
str1 := concat('min=', long2str(MinV), ' (', long2str(ActualMin), ')', crStr, 'max=', long2str(MaxV), ' (', long2str(ActualMax), ')', crStr)
else
str1 := concat('min=', long2str(MinV), crStr, 'max=', long2str(MaxV), crStr)
end
else
str1 := '';
RealToString((TickCount - StartTicks) / 60.0, 1, 2, str2);
ShowFrameRate(concat(Long2str(FramesToAverage), ' frames', crStr, str1, str2, ' seconds', crStr), StartTicks, FramesToAverage);
end;
UpdatePicWindow;
if AutoSelectAll then
KillRoi
else
ShowRoi;
if BlankFieldInfo <> nil then
CorrectShading;
if ShowIntegratedValues then with info^ do begin
fit := StraightLine;
nCoefficients := 2;
coefficient[2] := (MaxV - MinV) / 253.0;
coefficient[1] := MinV - coefficient[2];
nKnownValues := 0;
ZeroClip := false;
UpdateTitleBar;
if macro then
GenerateValues;
end else
if SumFrames and (info^.fit<>uncalibrated) then
RemoveDensityCalibration;
end;
function GetFGPixel (h, v: integer): integer;
var
offset: LongInt;
p: ptr;
begin
if FrameGrabber = QTvdig then begin
GetFGPixel := 0;
exit(GetFGPixel);
end;
with Info^ do begin
if (h < 0) or (v < 0) or (h >= fgWidth) or (v >= fgHeight) then begin
GetFGPixel := WhiteIndex;
exit(GetFGPixel);
end;
offset := ord4(v) * fgRowBytes + h;
if offset >= ord4(fgHeight) * fgRowBytes then begin
GetFGPixel := WhiteIndex;
exit(GetFGPixel);
end;
p := ptr(ord4(ptr(fgSlotBase)) + offset);
GetFGPixel := BAND(p^, 255);
end;
end;
procedure WaitForTrigger;
begin
StopDigitizing;
ShowWatch;
case FrameGrabber of
QuickCapture: begin
ControlReg^ := BitAnd($82, 255); {Wait for external trigger and capture one frame}
repeat
until (BitAnd(ControlReg^, $80) = $00) or Button; {Wait for it to complete}
end;
ScionLG3, ScionAg5, ScionVG5f: begin
ControlReg^ := $90; {Wait for external trigger and capture one frame}
repeat
until (BitAnd(ControlReg^, $80) = $80) or Button; {Wait for it to complete}
end;
otherwise
repeat
until Button;
end;
end;
procedure DoVideoSettingsDialog;
{Displays QuickTime video digitizer options dialog box}
const
grayID = 6;
color8ID = 7;
color24ID = 8;
fullID = 10;
oneHalfID = 11;
oneQuarterID = 12;
ntscID = 14;
palID = 15;
secamID =16;
builtinID = 17;
sVideoID = 18;
var
mylog: DialogPtr;
item, ignore: integer;
saveScale: integer;
saveBuiltin, sVideo: boolean;
wasDigitizing, WindowClosed, vdigError: boolean;
saveStandard: VideoDigitizerStandard;
saveMode: VideoDigitizerMode;
procedure SetCaptureModeButtons;
begin
SetDlogItem(mylog, grayID, ord(DigitizerMode = digitizeGrayscale));
SetDlogItem(mylog, color8ID, ord(DigitizerMode = digitizeColor));
SetDlogItem(mylog, color24ID, ord(DigitizerMode = digitizeRGB));
end;
procedure SetSizeButtons;
begin
SetDlogItem(mylog, fullID, ord(fgScale = 1));
SetDlogItem(mylog, oneHalfID, ord(fgScale = 2));
SetDlogItem(mylog, oneQuarterID, ord(fgScale = 4));
end;
procedure SetStandardButtons;
begin
SetDlogItem(mylog, ntscID, ord((DigitizerStandard = defaultStd) or (DigitizerStandard = NTSCStd)));
SetDlogItem(mylog, palID, ord(DigitizerStandard = palStd));
SetDlogItem(mylog, secamID, ord(DigitizerStandard = secamStd));
end;
begin
saveScale := fgScale;
saveBuiltIn := UseBuiltinDigitizer;
saveMode := DigitizerMode;
saveStandard := DigitizerStandard;
sVideo := VideoChannel = 1;
InitCursor;
mylog := GetNewDialog(320, nil, pointer(-1));
SetCaptureModeButtons;
SetSizeButtons;
SetStandardButtons;
SetDlogItem(mylog, builtinID, ord(UseBuiltinDigitizer));
SetDlogItem(mylog, sVideoID, ord(sVideo));
repeat
ModalDialog(nil, item);
if item = grayID then begin
DigitizerMode := digitizeGrayscale;
SetCaptureModeButtons;
end;
if item = color8ID then begin
DigitizerMode := digitizeColor;
SetCaptureModeButtons;
end;
if item = color24ID then begin
DigitizerMode := digitizeRGB;
SetCaptureModeButtons;
end;
if item = fullID then begin
fgScale := 1;
SetSizeButtons;
end;
if item = oneHalfID then begin
fgScale := 2;
SetSizeButtons;
end;
if item = oneQuarterID then begin
fgScale := 4;
SetSizeButtons;
end;
if item = ntscID then begin
DigitizerStandard := ntscStd;
SetStandardButtons;
end;
if item = palID then begin
DigitizerStandard := palStd;
SetStandardButtons;
end;
if item = secamID then begin
DigitizerStandard := secamStd;
SetStandardButtons;
end;
if item = builtinID then begin
UseBuiltinDigitizer := not UseBuiltinDigitizer;
SetDlogItem(mylog, builtinID, ord(UseBuiltinDigitizer));
end;
if item = sVideoID then begin
sVideo := not sVideo;
SetDlogItem(mylog, sVideoID, ord(sVideo));
end;
until (item = ok) or (item = cancel);
DisposeDialog(mylog);
if item = cancel then begin
fgScale := saveScale;
UseBuiltinDigitizer := saveBuiltIn;
DigitizerMode := saveMode;
DigitizerStandard := saveStandard;
exit(DoVideoSettingsDialog);
end;
if sVideo then
VideoChannel := 1
else
VideoChannel := 0;
wasDigitizing := digitizing;
StopDigitizing;
WindowClosed := false;
CloseVdig;
if (fgScale <> saveScale) or (UseBuiltinDigitizer <> saveBuiltIn) or (DigitizerStandard <> saveStandard) then begin
SelectCameraWindow;
with info^ do if PictureType = FrameGrabberType then begin
changes := false;
ignore := CloseAWindow(wptr);
WindowClosed := true;
end;
end;
if FrameGrabber = NoFrameGrabber then
LookForVDig(vdigError);
if wasDigitizing or WindowClosed then
StartDigitizing;
end;
procedure SetOffset (var offset, gain: integer);
begin
if offset < 0 then
offset := 0;
if offset > 255 then
offset := 255;
if offset > gain then
offset := gain;
DacLow := offset;
DacHigh := DacLow + (255 - gain);
end;
procedure SetGain (var offset, gain: integer);
begin
if gain < 0 then
gain := 0;
if gain > 255 then
gain := 255;
if gain < DacLow then
gain := DacLow;
DacHigh := DacLow + (255 - gain);
end;
procedure ShowChannel;
begin
SetDlogItem(VideoControl, FirstChannelID, ord(VideoChannel = 0));
SetDlogItem(VideoControl, FirstChannelID + 1, ord(VideoChannel = 1));
SetDlogItem(VideoControl, FirstChannelID + 2, ord(VideoChannel = 2));
SetDlogItem(VideoControl, FirstChannelID + 3, ord(VideoChannel = 3));
end;
procedure UpdateVideoControl;
begin
if VideoControl <> nil then
SetDlogItem(VideoControl, TriggerID, ord(ExternalTrigger));
end;
procedure ShowOffsetAndGain (offset, gain: integer);
var
str: str255;
begin
RealToString(offset, 3, 0, str);
if str[1] = ' ' then
str[1] := '0';
if str[2] = ' ' then
str[2] := '0';
SetDString(VideoControl, OffsetID, str);
RealToString(gain, 3, 0, str);
if str[1] = ' ' then
str[1] := '0';
if str[2] = ' ' then
str[2] := '0';
SetDString(VideoControl, GainID, str);
end;
procedure ShowVideoControl;
var
gain: integer;
begin
InitCursor;
VideoControl := GetNewDialog(130, nil, pointer(-1));
ShowChannel;
SetDlogItem(VideoControl, InvertID, ord(InvertVideo));
SetDlogItem(VideoControl, HighlightID, ord(HighlightSaturatedPixels));
SetDlogItem(VideoControl, TriggerID, ord(ExternalTrigger));
SetDlogItem(VideoControl, SyncID, ord(SyncMode = SeparateSync));
gain := 255 - (DacHigh - DacLow);
ShowOffsetAndGain(DacLow, gain);
end;
function NoScion:boolean;
var
NotFound:boolean;
begin
NotFound:=(FrameGrabber <> ScionLG3) and (FrameGrabber<>ScionAg5) and (FrameGrabber<>ScionVG5f);
if NotFound then PutError('Programmable offset and gain are only supported on Scion frame grabbers.');
NoScion:=NotFound;
end;
procedure DoVideoControl (item: integer);
var
i: integer;
OutOfRange, WasDigitizing: boolean;
offset, gain, inc, count: integer;
procedure SetVideoItem (item, value: integer);
begin
if VideoControl <> nil then
SetDlogItem(VideoControl, item, value);
end;
begin
InitCursor;
gain := 255 - (DacHigh - DacLow);
if (item >= FirstChannelID) and (item <= (FirstChannelID + 3)) then begin
VideoChannel := item - FirstChannelID;
if VideoControl <> nil then
ShowChannel;
if digitizing then
ResetFrameGrabber;
end;
if item = InvertID then begin
InvertVideo := not InvertVideo;
SetVideoItem(InvertID, ord(InvertVideo));
if digitizing then
ResetFrameGrabber;
end;
if item = HighlightID then begin
HighlightSaturatedPixels := not HighlightSaturatedPixels;
SetVideoItem(HighlightID, ord(HighlightSaturatedPixels));
if digitizing then begin
if HighlightSaturatedPixels then
HighlightPixels
else
LoadLUT(info^.ctable);
end;
end;
if item = TriggerID then begin
ExternalTrigger := not ExternalTrigger;
case FrameGrabber of
QuickCapture, ScionLG3, ScionAG5, ScionVG5f: begin
WasDigitizing := digitizing;
StopDigitizing;
if ExternalTrigger and WasDigitizing then
StartDigitizing;
end;
otherwise
ExternalTrigger := false;
end;
SetVideoItem(TriggerID, ord(ExternalTrigger));
end;
if item = SyncID then begin
if SyncMode <> SeparateSync then
SyncMode := SeparateSync
else
SyncMode := NormalSync;
case FrameGrabber of
ScionLG3, ScionAG5, ScionVG5f:
if digitizing then
ResetFrameGrabber;
QuickCapture: begin
PutError('Sync is not under program control on the QuickCapure card.');
SyncMode := NormalSync;
AbortMacro;
end;
otherwise
;
end;
SetVideoItem(SyncID, ord(SyncMode = SeparateSync));
end;
if (item >= OffsetUpID) and (item <= GainDownID) then begin
if NoScion then exit(DoVideoControl);
offset := DacLow;
inc := 1;
count := 0;
repeat
count := count + 1;
if count > 2 then
inc := 2;
if count > 4 then
inc := 5;
if count > 8 then
inc := 10;
case item of
OffsetUpID: begin
offset := offset + inc;
SetOffset(offset, gain);
end;
OffsetDownID: begin
offset := offset - inc;
SetOffset(offset, gain);
end;
GainUpID: begin
gain := gain + inc;
SetGain(offset, gain);
end;
GainDownID: begin
gain := gain - inc;
SetGain(offset, gain);
end;
end; {case}
ShowOffsetAndGain(DacLow, gain);
if Digitizing and (count > 1) then begin
DacLowReg^ := DacLow;
DacHighReg^ := DacHigh;
CaptureAndDisplayFrame;
if ContinuousHistogram then begin
ShowContinuousHistogram;
DrawHistogram
end
end
else
wait(5);
until not button;
end;
if item = ResetID then begin
if NoScion then exit(DoVideoControl);
DacLow := DefaultDacLow;
DacHigh := DefaultDacHigh;
gain := 255 - (DacHigh - DacLow);
ParamText(long2str(DacLow), long2str(gain), '', '');
ShowOffsetAndGain(DacLow, gain);
end;
if FramesToAverage < 2 then
FramesToAverage := 2;
if (FrameGrabber = ScionLG3) or (FrameGrabber=ScionAG5) or (FrameGrabber=ScionVG5f) then begin
DacLowReg^ := DacLow;
DacHighReg^ := DacHigh;
end;
end;
procedure ShowVideoDialog;
var
vdigError: boolean;
begin
if FrameGrabber = noFrameGrabber then begin
LookForVDig(vdigError);
if vdigError then begin
doVideoSettingsDialog;
exit(ShowVideoDialog);
end;
end;
if FrameGrabber = QTvdig then
doVideoSettingsDialog
else begin
if VideoControl = nil then
ShowVideoControl
else
SelectWindow(VideoControl);
end;
end;
end.